﻿/*
*    Qizx/open 3.0 beta
*
* This code is the open-source version of Qizx.
* Copyright (C) 2004-2009 Axyana Software -- All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License 
*  Version 1.1 (the "License"); you may not use this file except in 
*  compliance with the License. You may obtain a copy of the License at
*  http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
*  for the specific language governing rights and limitations under the
*  License.
*
* The Initial Developer of the Original Code is Xavier Franc - Axyana Software.
*
*/
using System;
using System.Xml;
using System.Collections;
using System.Xml.Schema;
using System.Qizx.Api;
using System.Collections.Generic;
using DataModelException = System.Qizx.Api.DataModelException;
using EvaluationException = System.Qizx.Api.EvaluationException;
using Node = System.Qizx.Api.Node;
using QName = System.Qizx.Api.QName;
using QizxException = System.Qizx.Api.QizxException;
using XMLPullStream = System.Qizx.Api.XMLPullStream;
using PushStreamToDOM = System.Qizx.Api.Util.PushStreamToDOM;
using XQDateTimeBase = System.Qizx.Api.Util.XQDateTimeBase;
using DateTimeException = System.Qizx.Api.Util.XQDateTimeException;
using Duration = System.Qizx.Api.Util.XQDuration;
using NamespaceContext = System.Qizx.Util.NamespaceContext;
using Comparison = System.Qizx.Util.Basic.Comparison;
using FileUtil = System.Qizx.Util.Basic.FileUtil;
using ComparisonContext = System.Qizx.XQuery.ComparisonContext;
using XQItem = System.Qizx.XQuery.XQItem;
using XQValue = System.Qizx.XQuery.XQValue;
using StringValue = System.Qizx.XQuery.Dt.StringValue;
using UntypedAtomicType = System.Qizx.XQuery.Dt.UntypedAtomicType;
using URI = System.Uri;

namespace System.Qizx.Xdm {
    [Serializable]
    public class XdmAttribute : XdmText {
        public static QName id;
        static XdmAttribute() {
            id = IQName.GetQName(string.Empty, "id");
        }
        public XdmElement OwnerElement {
            get {
                return this.ParentNode as XdmElement;
            }
        }

        public override QName NodeName {
            get {
                return _name.InternalQName;
            }
        }

        public override string NodeKind {
            get {
                return "attribute";
            }

        }
        public override XdmNodeType NodeType {
            get {
                return System.Qizx.Api.XdmNodeType.Attribute;
            }

        }

        internal XdmName _name;
        internal XdmAttribute(XdmName name, XdmDocument doc)
            : this(doc.DataModel, name.InternalQName) {
            _name = name;
        }
        internal XdmAttribute(CoreDataModel model, IQName name)
            : base(model) {
            _name = model.OwnerDocument.AddXmlName(name.Prefix, name.Name, name.Namespace, null);
        }


        #region Extensions
        public override void WriteContentTo(XmlWriter w) {
            for (BasicNode node = this.GetFirstChild(); node != null; node = node.NextSibling) {
                node.WriteTo(w);
            }
        }
        public override void WriteTo(XmlWriter w) {
            w.WriteStartAttribute(this._name.Prefix, this._name.LocalName, this._name.NamespaceURI);
            w.WriteString(this.TextValue);
            //TODO this.WriteContentTo(w);
            w.WriteEndAttribute();
        }

        public override IXdmSchemaInfo SchemaInfo {
            get {
                IXdmSchemaInfo schemaInfo = _name;
                if (schemaInfo.Validity == XmlSchemaValidity.NotKnown) {
                    XmlSchemaSet schemaSet = this.OwnerElement.Schemas;
                    KeyValuePair<XmlSchemaAttribute, XmlSchemaDatatype> type = schemaSet.GetAttributeDataType(this);
                    if (type.Value != null) {
                        XdmSchemaInfo schemaInfo2 = new XdmSchemaInfo();
                        schemaInfo2.Validity = XmlSchemaValidity.Valid;
                        schemaInfo2.SchemaAttribute = type.Key;
                        schemaInfo2.DataType = type.Value;
                        _name.Update(schemaInfo2);
                        return _name;
                    }
                }
                return schemaInfo;
            }
        }

        #endregion

        public override void AddText(string value) {
            string oldText = this.StringValue;
            base.AddText(value);
            UpdateIdAttribute(oldText, value);
        }

        public override string TextValue {
            get {
                return base.TextValue;
            }
            set {
                UpdateIdAttribute(this.StringValue, value);
                base.TextValue = value;
            }
        }

        public override string InnerText {
            get {
                return base.InnerText;
            }
            set {
                UpdateIdAttribute(this.StringValue, value);
                base.InnerText = value;
            }
        }

        public override string InnerXml {
            get {
                return base.InnerXml;
            }
            set {
                string oldValue = this.StringValue;
                base.InnerXml = value;
                UpdateIdAttribute(oldValue, this.StringValue);
            }
        }

        private void UpdateIdAttribute(string oldValue, string newValue) {
            if (id.Equals(this.NodeName)) {
                OwnerDocument.UpdateIdAttribute(this, oldValue, newValue);
            }
        }

        internal override Node GetOwnerDocument() {
            return _name.OwnerDocument;
        }

        public new XdmDocument OwnerDocument {
            get {
                return _name.OwnerDocument;
            }
        }

        public override string LocalName {
            get {
                return _name.LocalName;
            }
        }

        public override string Name {
            get {
                if (string.IsNullOrEmpty(_name.NamespaceURI))
                    return _name.LocalName;
                string prefix = this.GetPrefixOfNamespace(_name.NamespaceURI);
                if (string.IsNullOrEmpty(Prefix)) return _name.LocalName;
                return prefix + ":" + _name.LocalName;
            }
        }

        public override string NamespaceURI {
            get {
                return _name.NamespaceURI;
            }
        }
    }
}
